from django.contrib.auth import authenticate
from rest_framework import status
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework.throttling import  AnonRateThrottle, SimpleRateThrottle
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework import generics, permissions
from drf_yasg.utils import swagger_auto_schema
from .docs import AuthViewsetDocs
from .models import *
from .serializers import *
from utils.verification import send_verification_code, verify_code, is_phone
from rest_framework_simplejwt.authentication import JWTAuthentication
from utils.qiniu_tools import ImageHandler

class SendCodeThrottle(AnonRateThrottle):
    scope = 'send_code'
class IPRateThrottle(SimpleRateThrottle):
    scope = 'ips'
    
    def get_cache_key(self, request, view):
        return self.get_ident(request)

class LoginRateThrottle(IPRateThrottle):
    scope = 'login'
    def get_cache_key(self, request, view):
        # 对于未认证用户使用IP地址
        ident = self.get_ident(request)
        return self.cache_format % {
            'scope': self.scope,
            'ident': ident
        }

class AuthViewSet(ViewSet):
    parser_classes = [JSONParser,FormParser, MultiPartParser]  # 添加解析器以支持表单数据
    
    @swagger_auto_schema(**AuthViewsetDocs['refresh_token'])
    @action(methods=['post'], detail=False, url_path='refresh-token', url_name='refresh-token')
    def refresh_token(self,request):
        refresh_token = request.data.get('refresh')
        if not refresh_token:
            return Response({'status': 'failed','message': '未提供刷新令牌'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            refresh_token=RefreshToken(refresh_token)
            refresh_token.verify()#验证令牌
            access_token=str(refresh_token.access_token)
            return Response({'status': 'success','access': access_token}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'status': 'failed','message': '无效的刷新令牌'}, status=status.HTTP_400_BAD_REQUEST)
    
    @swagger_auto_schema(**AuthViewsetDocs['login'])
    @action(methods=['post'], detail=False, url_path='login', url_name='login', throttle_classes=[LoginRateThrottle])
    def login(self, request):
        serializer = LoginSerializer(data=request.data)
        if serializer.is_valid():
            username = serializer.validated_data['username']
            password = serializer.validated_data['password']
            user = authenticate(username=username, password=password)
            if user:
                refresh = RefreshToken.for_user(user) # 生成刷新和访问令牌
                return Response({
                    'status': 'success',
                    'refresh': str(refresh),
                    'access': str(refresh.access_token),
                }, status=status.HTTP_200_OK)
            return Response({'status': 'failed', 'message': '用户名或密码错误'}, status=status.HTTP_401_UNAUTHORIZED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @swagger_auto_schema(**AuthViewsetDocs['register'])
    @action(methods=['post'], detail=False, url_path='register', url_name='register')
    def register(self, request):
        serializer = RegisterSerializer(data=request.data)
        if serializer.is_valid():
            # 验证验证码
            phone = serializer.validated_data['phone']
            captcha = request.data.get('captcha', None)
            if not verify_code(phone, captcha, scene='register')[0]:
                return Response({'status': 'failed', 'message': '验证码错误'}, status=status.HTTP_400_BAD_REQUEST)
                
            serializer.save()#创建用户信息
            return Response({'status': 'success', 'message': '注册成功'}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    @swagger_auto_schema(**AuthViewsetDocs['logout'])
    @action(methods=['post'], detail=False, url_path='logout', url_name='logout', permission_classes=[IsAuthenticated])
    def logout(self, request):
        try:
            refresh_token = request.data.get('refresh')
            if refresh_token:
                token = RefreshToken(refresh_token)
                token.blacklist()  # 将令牌添加到黑名单
            return Response({'status': 'success','message': '退出成功'}, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'status': 'failed','message': 'token无效，退出失败'}, status=status.HTTP_400_BAD_REQUEST)
        
    @swagger_auto_schema(**AuthViewsetDocs['send_code'])
    @action(methods=['post'], detail=False, url_path='send-code', url_name='send-code', throttle_classes=[SendCodeThrottle])
    def send_code(self, request):
        serializer = SendCodeSerializer(data=request.data)
        if not serializer.is_valid():# 这里会自动触发validate方法
            return Response({'status': 'failed', 'message': '参数错误', 'errors': serializer.errors},status=status.HTTP_400_BAD_REQUEST)
    
        scene = serializer.validated_data['scene']
        phone = serializer.validated_data.get('phone')
        email = serializer.validated_data.get('email')
    
        # 场景校验逻辑
        if scene == 'register':
            # 注册场景：检查手机号是否已存在
            if not phone:
                return Response({'status': 'failed', 'message': '注册需要提供手机号'}, 
                              status=status.HTTP_400_BAD_REQUEST)
            if CustomUser.objects.filter(phone=phone).exists():
                return Response({'status': 'failed', 'message': '手机号已注册'}, 
                               status=status.HTTP_400_BAD_REQUEST)
            target = phone
        elif scene == 'reset_pwd':
            # 密码找回场景：检查手机号或邮箱是否存在
            if phone:
                if not CustomUser.objects.filter(phone=phone).exists():
                    return Response({'status': 'failed', 'message': '手机号未注册'}, 
                                   status=status.HTTP_404_NOT_FOUND)
                target = phone
            else:
                if not CustomUser.objects.filter(email=email).exists():
                    return Response({'status': 'failed', 'message': '邮箱未注册'}, 
                                   status=status.HTTP_404_NOT_FOUND)
                target = email
        
        # 发送验证码
        result = send_verification_code(target, scene=scene)
        return Response({'status': 'success', 'message': '验证码已发送', 'dev_code': result.get('dev_code')}, status=status.HTTP_200_OK)
    
    @swagger_auto_schema(**AuthViewsetDocs['check_code'])
    # 点击确认验证码按钮触发
    @action(methods=['post'], detail=False, url_path='check-code', url_name='check-code')
    def check_code(self, request):
        serializer = VerifyCodeSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({'status': 'failed', 'message': '参数错误'}, 
                           status=status.HTTP_400_BAD_REQUEST)
        scene = serializer.validated_data['scene']
        target = serializer.validated_data.get('phone') or serializer.validated_data.get('email')
        code = serializer.validated_data['code']
        
        is_valid, error_msg = verify_code(target, code, scene)
        if not is_valid:
            return Response({'status': 'failed', 'message': error_msg},status=status.HTTP_400_BAD_REQUEST)
        
        if scene == 'reset_pwd':
            user = CustomUser.objects.get(phone=target) if is_phone(target) else CustomUser.objects.get(email=target)
            refresh = RefreshToken.for_user(user)
            return Response({
                'status': 'success',
                'token': str(refresh.access_token)  # 返回access token
            }, status=status.HTTP_200_OK)
        
        return Response({'status': 'success'}, status=status.HTTP_200_OK)
    @swagger_auto_schema(**AuthViewsetDocs['reset_password'])
    #点击确认重置密码按钮触发
    @action(methods=['post'], detail=False, url_path='reset-password', url_name='reset-password')
    def reset_password(self, request):
        # 1. 序列化器验证传入的数据
        serializer = ResetPasswordSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {'status': 'failed', 'message': '参数错误', 'errors': serializer.errors},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            # 2. 根据提供的手机号或邮箱找到用户
            phone = request.data.get('phone')
            email = request.data.get('email')
            
            if phone:
                user = CustomUser.objects.get(phone=phone)
            elif email:
                user = CustomUser.objects.get(email=email)
            else:
                return Response(
                    {'status': 'failed', 'message': '必须提供手机号或邮箱'},
                    status=status.HTTP_400_BAD_REQUEST
                )

            # 3. 验证token
            auth_header = request.headers.get('Authorization')
            if not auth_header or not auth_header.startswith('Bearer '):
                return Response(
                    {'status': 'failed', 'message': '未提供有效的Authorization头'},
                    status=status.HTTP_401_UNAUTHORIZED
                )
            token = auth_header.split(' ')[1]

            # 4. 验证token是否属于该用户
            jwt_auth = JWTAuthentication()
            validated_token = jwt_auth.get_validated_token(token)
            token_user = jwt_auth.get_user(validated_token)

            if token_user.id != user.id:
                
                return Response(
                    {'status': 'failed', 'message': '无效的重置密码请求'},
                    status=status.HTTP_403_FORBIDDEN
                )
            # 5. 重置密码
            user.set_password(request.data['password'])
            user.save()

            return Response(
                {'status': 'success', 'message': '密码重置成功'},
                status=status.HTTP_200_OK
            )
            
        except CustomUser.DoesNotExist:
            return Response(
                {'status': 'failed', 'message': '未找到对应的用户账号'},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {'status': 'failed', 'message': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @swagger_auto_schema(**AuthViewsetDocs['upload_avatar'])
    @action(methods=['post'], detail=False, url_path='upload-avatar', url_name='upload-avatar', permission_classes=[IsAuthenticated])
    def upload_avatar(self, request):
        if 'avatar' not in request.FILES:
            return Response(
                {'status': 'failed', 'message': '未提供头像文件'},status=status.HTTP_400_BAD_REQUEST)
        avatar_file = request.FILES['avatar']
        # 验证文件类型和大小
        if avatar_file.size > 2 * 1024 * 1024:  # 2MB限制
            return Response(
                {'status': 'failed', 'message': '头像文件不能超过2MB'},
                status=status.HTTP_400_BAD_REQUEST
            )
        # 验证文件类型
        if not avatar_file.content_type.startswith('image/'):
            return Response(
                {'status': 'failed', 'message': '仅支持图片文件'},
                status=status.HTTP_400_BAD_REQUEST
            )
        # 检测不适当内容
        try:
            from utils.nsfwChecker import NSFWChecker
            checker = NSFWChecker()
            checker.check_images([avatar_file])  # 检测不适当内容
            handler = ImageHandler()
            # 先删除旧头像
            if request.user.avatar_key:
                try:
                    old_key = request.user.avatar_key.split('/')[-1] if 'http' in request.user.avatar_key else request.user.avatar_key
                    handler.delete_file(old_key)
                except Exception as e:
                    print(f"删除旧头像失败: {str(e)}")
            
            # 上传新头像
            avatar_key = handler.upload_avatar(avatar_file, request.user.uid)
            
            # 保存到用户模型
            request.user.avatar_key = avatar_key
            request.user.save()
            
            return Response({
                'status': 'success',
                'avatar_url': request.user.avatar_url
            }, status=status.HTTP_200_OK)
            
        except ValueError as e:
            # 内容审核不通过
            return Response(
                {'status': 'failed', 'message': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            print(f"上传头像失败: {str(e)}")
            return Response(
                {'status': 'failed', 'message': '上传头像失败'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    @swagger_auto_schema(**AuthViewsetDocs['get_avatar_url'])
    # 首页获取头像的专用接口（只返回头像URL）
    @action(methods=['get'], detail=False, url_path='avatar-url', url_name='avatar-url')
    def get_avatar_url(self, request):
        if not request.user.is_authenticated:
            return Response({'status': 'failed', 'message': '未登录'}, status=status.HTTP_401_UNAUTHORIZED)
        
        if not request.user.avatar_key:
            return Response({'status': 'failed', 'message': '用户未设置头像'}, status=status.HTTP_404_NOT_FOUND)
        
        return Response({
            'status': 'success',
            'avatar_url': request.user.avatar_url  # 使用模型属性确保一致性
        }, status=status.HTTP_200_OK)
    
    @swagger_auto_schema(**AuthViewsetDocs['get_user_info'])
    @action(methods=['get'], detail=False, url_path='user-info', url_name='user-info', permission_classes=[IsAuthenticated])
    def get_user_info(self, request):
        user = request.user
        return Response({
            'username': user.username,
            'uid': user.uid,
            'avatar_url': user.avatar_url if user.avatar_key else '',
            'credit_score': str(user.credit_score)
        }, status=status.HTTP_200_OK)
    
    @swagger_auto_schema(**AuthViewsetDocs['reset_phone_or_email'])
    @action(methods=['post'], detail=False, url_path='reset-phone-or-email', url_name='reset-phone-or-email', permission_classes=[IsAuthenticated])
    def reset_phone_or_email(self, request):
        serializer = ResetPhoneOrEmailSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({'status': 'failed','message': '参数错误', 'errors': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
        user = request.user
        new_email = serializer.validated_data.get('new_email')
        new_phone = serializer.validated_data.get('new_phone')
        if new_email:
            if CustomUser.objects.filter(email=new_email).exclude(id=user.id).exists():
                return Response({'status': 'failed','message': '邮箱已被他人注册或和你原来的一样'}, status=status.HTTP_400_BAD_REQUEST)
            user.email = new_email
        elif new_phone:
            if CustomUser.objects.filter(phone=new_phone).exclude(id=user.id).exists():
                return Response({'status': 'failed','message': '手机号已被他人注册或和你原来的一样'}, status=status.HTTP_400_BAD_REQUEST)
            user.phone = new_phone
        user.save()
        return Response({'status':'success','message': '修改成功'}, status=status.HTTP_200_OK)


class IsOwnerPermission(permissions.BasePermission):
    """确保用户只能操作自己的地址"""
    def has_object_permission(self, request, view, obj):
        return obj.user == request.user

class AddressListCreateView(generics.ListCreateAPIView):
    
    serializer_class = AddressSerializer
    # 显式设置权限：必须登录 + 自定义所有权检查
    permission_classes = [permissions.IsAuthenticated, IsOwnerPermission]  # 覆盖全局的 AllowAny

    def get_queryset(self):
        return Address.objects.filter(user=self.request.user).order_by('-created_at')

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

class AddressDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Address.objects.all()
    serializer_class = AddressSerializer
    # 同样显式设置权限
    permission_classes = [permissions.IsAuthenticated, IsOwnerPermission]
    lookup_field = 'id'